import { parseHTMLToAST as parseHTML } from "./paser-html";
import { generate } from "./generate";

/**
 * AST 是描述语言本身语法的
 * VDom 是描述 DOM 元素的
 * 
 * 把模板生成 AST 语法树，再将 AST 语法树转换成字符串拼接起来后，又通过 with 生成 render 函数返回
 * 
 * @param {*} template 模板字符串
 * @returns 返回 render 函数
 */
export function compileToFunction(template) {
    /**
     * 把 template 解析成 AST 语法树， 用对象来描述原生（html）“语法”的，就叫 AST 语法树 (这里是语法)
     * 例如：
     * <div id="app">
     *  <p>Hello</p>
     * </div>
     * 使用 AST（抽象） 语法树描述语法：
     * const root = {
     *  tag: 'div',
     *  attrs: [{name: 'id', value: 'app'}],
     *  type: 1, // 表示元素类型
     *  parent: null,
     *  children: [{
     *      tag: 'p',
     *      attrs:[],
     *      type: 1, // 表示元素类型
     *      parent: root
     *      children: [{
     *          text: 'Hello',
     *          type: 3  // 表示文本类型
     *      }]  // 如此嵌套下去构成 AST 语法树
     *  }]
     * }
     */
    // console.log('获取模板字符串：', template);

    const root = parseHTML(template); // 模板生成 AST 语法树
    /**
     * 通过一些辅助函数 _c(), _v(), _s(), 生成虚拟DOM，最后返回的就是 render 函数了
     * <div id="app"><p>hello {{name}}</p>world</div>
     * // 将上面的模板转成 AST 后在通过 _c(),_v(),_s() 转成 js 语法，生成虚拟 DOM
     * _c("div", { id: "app" }, _c("p", undefined, _v("hello " + _s(name))), _v("world")) // 这就会生成虚拟DOM
     */
    const vnode = generate(root); // 将 AST 生成虚拟 DOM

    // 将生成的虚拟 DOM 转换成 render 函数
    // 这里就是虚拟 DOM，用对象来描述 DOM “节点”的，这里是描述真实 DOM 树的结构，就叫虚拟 DOM， 类似于 JOSN 的数据格式，比 AST 描述更详细
    /**
     * <div id="app">
     *  <p>Hello</p>
     * </div>
     * {
     *  tag: 'div'
     *  data: {id: app}
     *  children: {}
     * }
     */
    const renderFn = new Function(`with(this){return ${vnode};}`);

    // 返回 render 函数，就是虚拟 DOM 了
    return renderFn;
}